using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

using SBPweb.Controls.Windows;
using SBPweb.Themes.Windows;
using SBPweb.Themes.Windows.Skins;

namespace SBPweb.Controls.Windows.Editors
{
	/// <summary>
	/// Class of RadioButton
	/// </summary>
	[ToolboxBitmap(typeof(System.Windows.Forms.RadioButton))]
	public partial class RadioButton : System.Windows.Forms.RadioButton, ISkinnable
	{
		#region Private members

		private bool mUseDefaultSkin;
		private Skin mSkin;

		private object mValue;
		
		private MouseEventState mMState = MouseEventState.None;

		#endregion

		#region Constructor logic

		/// <summary>
		/// Constructor of RadioButton
		/// </summary>
		public RadioButton()
		{
			SetStyle(); 
			RegisterEventHandlers();
		}

		/// <summary>
		/// Constructor of RadioButton
		/// </summary>
		/// <param name="skin">skin</param>
		public RadioButton(Skin skin)
		{
			mSkin = skin;

			SetStyle();
			RegisterEventHandlers();
		}

		private void SetStyle()
		{
			base.SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
		}

		private void RegisterEventHandlers()
		{
			this.MouseEnter += new EventHandler(this_MouseEnter);
			this.MouseLeave += new EventHandler(this_MouseLeave);
			this.MouseDown += new MouseEventHandler(this_MouseDown);
			this.MouseUp += new MouseEventHandler(this_MouseUp);
			this.MouseHover += new EventHandler(this_MouseHover);
		}

		#endregion

		#region Custom draw
		/// <summary>
		/// On paint
		/// </summary>
		/// <param name="e">event args</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			StringFormat sf;
			SizeF size;

			if (Skin == null)
			{
				base.OnPaint(e);
				sf = new StringFormat(StringFormat.GenericDefault);
				size = e.Graphics.MeasureString(this.Text, this.Font, new SizeF(this.ClientRectangle.Width, this.ClientRectangle.Height), sf);
				this.MinimumSize = new System.Drawing.Size(Convert.ToInt32(size.Width + 5), Convert.ToInt32(size.Height + 5));
				return;
			}

			base.OnPaintBackground(e);

			System.Drawing.Image img = Skin.GetImageFromBitmapResource(Skin.KeyPrefix + "editors.radiobutton.png");

			int imgCount = 8;
			int imgWidth = img.Width;
			int imgHeight = (Int32)(img.Height / imgCount);
			int imgTop;

			switch (mMState)
			{
				default:
				case MouseEventState.None:
					if (this.Enabled)
					{
						imgTop = (this.Checked ? 4 : 0) * imgHeight;
					}
					else
					{
						imgTop = (this.Checked ? 7 : 3) * imgHeight;
					}
					break;
				case MouseEventState.OnHover:
					imgTop = (this.Checked ? 5 : 1) * imgHeight;
					break;
				case MouseEventState.OnDown:
					if (this.Enabled)
					{
						imgTop = (this.Checked ? 6 : 2) * imgHeight;
					}
					else
					{
						imgTop = (this.Checked ? 7 : 3) * imgHeight;
					}
					break;
			}

			#region Image parts
			Rectangle iM = new Rectangle(0, imgTop, imgWidth, imgHeight);
			#endregion

			#region Window Parts
			sf = new StringFormat(StringFormat.GenericDefault);
			size = e.Graphics.MeasureString(this.Text, this.Font, new SizeF(this.ClientRectangle.Width, this.ClientRectangle.Height), sf);
			int cTop = (ClientRectangle.Height + ClientRectangle.Top) / 2 - imgHeight / 2;
			int cLeft;
			int offsetX;
			
			if(this.RightToLeft == RightToLeft.No)
			{
				cLeft = 0;
				offsetX = imgWidth;
			}
			else
			{
				cLeft = (int)size.Width;
				offsetX = 0;
			}

			Rectangle tM = new Rectangle(cLeft, cTop, imgWidth, imgHeight);
			#endregion

			e.Graphics.DrawImage(img, tM, iM, GraphicsUnit.Pixel);

			DrawText(e, new Point(offsetX, 0), size);
		}

		private void DrawText(PaintEventArgs e, Point p, SizeF size)
		{
			float xLeft, xCenter, xRight, yTop, yMiddle, yBottom;
			float textX, textY;

			int canvasWidth = this.ClientRectangle.Width;
			int canvasHeight = this.ClientRectangle.Height ;

			xLeft = p.X;
			xCenter = (canvasWidth - size.Width) / 2;
			xRight = canvasWidth - size.Width;

			yTop = p.Y;
			yMiddle = (canvasHeight - size.Height) / 2 ;
			yBottom = canvasHeight - size.Height ;

			switch (this.TextAlign)
			{
				case ContentAlignment.TopLeft:
					textX = xLeft;
					textY = yTop;
					break;
				case ContentAlignment.TopCenter:
					textX = xCenter;
					textY = yTop;
					break;
				case ContentAlignment.TopRight:
					textX = xRight;
					textY = yTop;
					break;
				case ContentAlignment.MiddleLeft:
					textX = xLeft;
					textY = yMiddle;
					break;
				case ContentAlignment.MiddleCenter:
					textX = xCenter;
					textY = yMiddle;
					break;
				case ContentAlignment.MiddleRight:
					textX = xRight;
					textY = yMiddle;
					break;
				case ContentAlignment.BottomLeft:
					textX = xLeft;
					textY = yBottom;
					break;
				case ContentAlignment.BottomCenter:
					textX = xCenter;
					textY = yBottom;
					break;
				case ContentAlignment.BottomRight:
					textX = xRight;
					textY = yBottom;
					break;
				default:
					textX = 0;
					textY = 0;
					break;
			}

			e.Graphics.TextRenderingHint = Skin.TextRenderingHint;
			if (this.Enabled)
			{
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(Skin.CachedProperties.ControlTextColor), new RectangleF(textX, textY, textX + size.Width, textY + size.Height));
			}
			else
			{
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(Skin.CachedProperties.ControlDisabledTextColor), new RectangleF(textX, textY, textX + size.Width, textY + size.Height));
			}
			// Set minimum size
			this.MinimumSize = new System.Drawing.Size(Convert.ToInt32(size.Width + 5), Convert.ToInt32(size.Height + 5));
		}

		/// <summary>
		/// On background paint
		/// </summary>
		/// <param name="e">event args</param>
		protected override void OnPaintBackground(PaintEventArgs e)
		{
		}

		#endregion

		#region Events
		void this_MouseEnter(object sender, EventArgs e)
		{
			mMState = MouseEventState.OnHover;
		}

		void this_MouseUp(object sender, MouseEventArgs e)
		{
			mMState = MouseEventState.OnHover;
			this.Invalidate();
		}

		void this_MouseDown(object sender, MouseEventArgs e)
		{
			mMState = MouseEventState.OnDown;
			this.Invalidate();
		}

		void this_MouseLeave(object sender, EventArgs e)
		{
			mMState = MouseEventState.None;
			this.Invalidate();
		}

		void this_MouseHover(object sender, EventArgs e)
		{
			mMState = MouseEventState.OnHover;
			this.Invalidate();
		}

		#endregion

		#region Properties

		public object Value
		{
			get
			{
				return mValue;
			}
			set
			{
				mValue = value;
			}
		}

		#endregion

		#region ISkinnable Members

		/// <summary>
		/// Use default skin?
		/// </summary>
		[Category("Look && feel")]
		public bool UseDefaultSkin
		{
			get
			{
				return mUseDefaultSkin;
			}
			set
			{
				mUseDefaultSkin = value;
				Invalidate();
			}
		}

		/// <summary>
		/// Used skin
		/// </summary>
		[Category("Look && feel")]
		public Skin Skin
		{
			get
			{
				if (this.UseDefaultSkin)
				{
					return DefaultLookAndFeel.Skin;
				}

				return mSkin;
			}
			set
			{
				mSkin = value;
				Invalidate();
			}
		}

		#endregion
	}
}
